/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.quantprinciple.models.timevalue;

import com.quantprinciple.applet.dataanalysis.TableToChartTabbedPane;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JFrame;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

/**
 *
 * @author bryce
 */
public class LoanAmatorization {
	private double principle = 200000L   ;
    private double interestRate = 7.00;
    private double compoundingPeriods = 365;
    private double termYears = 30;
    private double paymentsPerTerm = 12;
    private double monthlyRate;
    private double monthlyPayment;
    private Object[][] amatorizationTable;

	/**
	 * This constructor will be called by all constructors to ensure that 
	 * monthlyRate is set.
	 */
	{
		recalculateMontlyRate();
		recalculateMontlyPayment();
		recalculateAmatorizationTable();
	}

	public LoanAmatorization(){

	}

	/**
	 * For a typicall Loan, you will pay closing costs for interest up until the 1st of the next month.
	 * 
	 */
	private void recalculateAmatorizationTable(){

		Calendar c  = Calendar.getInstance();
		c.setTime(new Date());
		int Month = c.get(Calendar.MONTH);
		int DayOfMonth = c.get(Calendar.DAY_OF_MONTH);
		int Year = c.get(Calendar.YEAR);
		//int daysInMonth = c.get(Calendar.)

		Date loanDate = c.getTime();
		c.add(Calendar.MONTH, 1);
		c.set(Calendar.DAY_OF_MONTH, 1);
		Date amatorizationStartDate = c.getTime();
		int closingDays = (int)(amatorizationStartDate.getTime() - loanDate.getTime())/(1000*60*60*24);
		double OnePlusR = 1+getInterestRate()/100D/(double)365;
		double closingInterestPayment = getPrinciple()*Math.pow(OnePlusR, OnePlusR);

		int terms = (int)(termYears*paymentsPerTerm);
		amatorizationTable = new Object[terms][5];
		double currentBalance = getPrinciple();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		for(int i =0;i<terms;++i){
		    c.add(Calendar.MONTH,1);
		    String dateString = sdf.format(c.getTime());
		    amatorizationTable[i][0]=dateString;
		    amatorizationTable[i][1]=Math.min(monthlyPayment, currentBalance);
		    double currentInterest = monthlyRate*currentBalance/100;
		    double principlePayment = monthlyPayment - currentInterest;
		    amatorizationTable[i][2]=currentInterest;
		    amatorizationTable[i][3]=principlePayment;
		    currentBalance-=principlePayment;
		    amatorizationTable[i][4]=currentBalance;
		}
	}
	
	private void recalculateMontlyRate(){

		double OnePlusR = 1+getInterestRate()/100D/(double)getCompoundingPeriods();
		double exp1 = (double)getCompoundingPeriods()/12D;
		monthlyRate = (Math.pow(OnePlusR, exp1) -1)*100;
		
	}

	private void recalculateMontlyPayment(){
		double terms = getTermYears()*getPaymentsPerTerm();
		double n = terms;
		double r = getMonthlyRate()/100D;
		double w_prime= r/(1-Math.pow((1+r),-n));

		monthlyPayment = w_prime*getPrinciple();


	}
	
	public static void main(String args[]){
		LoanAmatorization la = new LoanAmatorization();
		System.out.println("Monthly Rate: " + la.getMonthlyRate());
		System.out.println("Annual Rate Compounded Monthly: " + la.getMonthlyRate()*12);
		System.out.println(" Monthly payment: " + la.getMonthlyPayment());
		int terms =la.amatorizationTable.length;
		for(int i =0;i<terms;++i){
		    StringBuilder sb = new StringBuilder();
		    sb.append("date: ").append(la.amatorizationTable[i][0]).append(" int: ")
			    .append(la.amatorizationTable[i][2])
			    .append(" p-red ").append(la.amatorizationTable[i][3])
			    .append(" balance ").append(la.amatorizationTable[i][4]);
		    System.out.println(sb.toString());
		}

		JFrame fram = new JFrame();
	    TableToChartTabbedPane ttcp = new TableToChartTabbedPane();


	    ttcp.setDataViewTab(la.getTestingTableModel());
	    ttcp.setChartView();
	    ttcp.updateChartView();
	    fram.add(ttcp.getTabbedPane());
	    fram.setVisible(true);

	}

    /**
     * @return the principle
     */
    public double getPrinciple() {
	return principle;
    }

    /**
     * @param principle the principle to set
     */
    public void setPrinciple(double principle) {
	this.principle = principle;
    }

    /**
     * @return the interestRate
     */
    public double getInterestRate() {
	return interestRate;
    }

    /**
     * @param interestRate the interestRate to set
     */
    public void setInterestRate(double interestRate) {
	this.interestRate = interestRate;
    }

    /**
     * @return the compoundingPeriods
     */
    public double getCompoundingPeriods() {
	return compoundingPeriods;
    }

    /**
     * @param compoundingPeriods the compoundingPeriods to set
     */
    public void setCompoundingPeriods(double compoundingPeriods) {
	this.compoundingPeriods = compoundingPeriods;
    }

    /**
     * @return the termYears
     */
    public double getTermYears() {
	return termYears;
    }

    /**
     * @param termYears the termYears to set
     */
    public void setTermYears(double termYears) {
	this.termYears = termYears;
    }

    /**
     * @return the paymentsPerTerm
     */
    public double getPaymentsPerTerm() {
	return paymentsPerTerm;
    }

    /**
     * @param paymentsPerTerm the paymentsPerTerm to set
     */
    public void setPaymentsPerTerm(double paymentsPerTerm) {
	this.paymentsPerTerm = paymentsPerTerm;
    }

    /**
     * @return the monthlyRate
     */
    public double getMonthlyRate() {
	return monthlyRate;
    }

    /**
     * @return the monthlyPayment
     */
    public double getMonthlyPayment() {
	return monthlyPayment;
    }

    /**
     * @return the amatorizationTable
     */
    public Object[][] getAmatorizationTable() {
	return amatorizationTable;
    }
    private TableModel getTestingTableModel(){
	    Object[][] data = amatorizationTable;
	    Object[] names = new Object[] {"time","Payment", "Interest" , "Principle","current balance"};
	    TableModel tm = new DefaultTableModel(data,names);
	    return tm;
    }


}
